package com.swak.rpc.config;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swak.registry.URL;
import com.swak.rpc.Exporter;
import com.swak.rpc.config.model.ServiceMetadata;
import com.swak.utils.Lists;
import com.swak.utils.StringUtils;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * ServiceBean.
 * 
 * @author lifeng
 */
@Getter
@Setter
@Accessors(chain = true)
public class ServiceConfig<T> extends AbstractServiceConfig {
	private static final long serialVersionUID = 1L;
	private static final Logger logger = LoggerFactory.getLogger(ServiceConfig.class);
	private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
	protected String interfaceName;
	protected Class<?> interfaceClass;
	protected T ref;
	private transient volatile boolean exported;
	private transient volatile boolean unexported;
	private ServiceMetadata meta;
	private String serviceName;
	private ProviderConfig provider;

	public ServiceConfig() {
		meta = new ServiceMetadata();
	}

	public boolean isExported() {
		return exported;
	}

	public boolean isUnexported() {
		return unexported;
	}

	public String getServiceName() {
		if (!StringUtils.isBlank(serviceName)) {
			return serviceName;
		}
		String generateVersion = version;
		String generateGroup = group;

		if (StringUtils.isBlank(version) && provider != null) {
			generateVersion = provider.getVersion();
		}

		if (StringUtils.isBlank(group) && provider != null) {
			generateGroup = provider.getGroup();
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("ServiceBean:");

		if (!StringUtils.isBlank(generateGroup)) {
			stringBuilder.append(generateGroup);
		}

		stringBuilder.append("/").append(interfaceName);

		if (!StringUtils.isBlank(generateVersion)) {
			stringBuilder.append(":").append(generateVersion);
		}

		serviceName = stringBuilder.toString();
		return serviceName;
	}

	public synchronized void export() {
		meta.setVersion(getVersion());
		meta.setGroup(getGroup());
		meta.setServiceType(getInterfaceClass());
		meta.setServiceInterfaceName(getInterfaceName());
		meta.setTarget(getRef());
		this.doExport();
	}

	protected synchronized void doExport() {
		if (unexported) {
			throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!");
		}
		if (exported) {
			return;
		}
		exported = true;
		doExportUrls();
	}

	private void doExportUrls() {
		List<URL> registryURLs = Lists.newArrayList();
		for (ProtocolConfig protocolConfig : protocols) {
			this.doExportUrls(protocolConfig, registryURLs);
		}
	}

	private void doExportUrls(ProtocolConfig config, List<URL> registryURLs) {

	}

	public void unexport() {
		if (!exported) {
			return;
		}
		if (unexported) {
			return;
		}
		if (!exporters.isEmpty()) {
			for (Exporter<?> exporter : exporters) {
				try {
					exporter.unexport();
				} catch (Throwable t) {
					logger.warn("Unexpected error occurred when unexport " + exporter, t);
				}
			}
			exporters.clear();
		}
		unexported = true;
	}
}
